global print_c
global out_byte
global in_byte
global disable_irq
global enable_irq
global clear_screen2
global reset_sec_reg
global port_read
global port_write

extern g_text_attr
extern g_cur_pos

print_c: ;void (*)(char c)
    mov ah, byte [g_text_attr]
    mov al, byte [esp + 4]
    movzx ecx, word [g_cur_pos]
    mov [gs:ecx], ax
    ret

reset_sec_reg:
    mov dx, ss
    mov ds, dx ;set to ring0
    mov es, dx ;set to ring0
    mov ax, (3*8)
    mov gs, ax
    ret

clear_screen2: ;void (*)(void)
    mov ecx, 0 ;max_row=25 max_col=80  共25行，80列 160*row+2*col  max=160*24+80*2 = 4000  =>[0, 3999]
    mov al, ' ';0
    mov ah, 0x0F
    c_s_loop:
        cmp ecx, 4000
        jz c_s_fin
        mov [gs:ecx], ax
        add ecx, 2
    jmp c_s_loop
    c_s_fin:
    mov [g_cur_pos], dword 0
    ret

out_byte: ;void (*)(u16 port, u8 value);
    mov edx, [esp + 4] ;port
    mov al, [esp + 4 + 4]    ; value
    out dx, al
    nop; 一点延迟
    nop
    ret

in_byte: ;u8 (*)(u16 port);
    mov edx, [esp + 4] ; port
    xor eax, eax
    in al, dx
    nop; 一点延迟
    nop
    ret


INT_M_CTLMASK equ 0x21; setting bits in this port disables ints   <Master>
INT_S_CTLMASK equ 0xA1; setting bits in this port disables ints   <Slave>

disable_irq: ;void (*)(int irq_no)
    mov ecx, [esp + 4]
    pushf ;push eflags
    cli
    mov ah, 1
    rol ah, cl ;cl=[0,15] ah = 1 << (irq_no % 8)
    cmp     cl, 8
    jae     disable_8       ; disable irq >= 8 at the slave 8259
    disable_0:
        in      al, INT_M_CTLMASK
        test    al, ah
        jnz     dis_already     ; already disabled?
        or      al, ah
        out     INT_M_CTLMASK, al       ; set bit at master 8259
        popf
        mov     eax, 1      ; disabled by this function
        ret
    disable_8:
        in      al, INT_S_CTLMASK
        test    al, ah
        jnz     dis_already     ; already disabled?
        or      al, ah
        out     INT_S_CTLMASK, al       ; set bit at slave 8259
        popf
        mov     eax, 1      ; disabled by this function
        ret
    dis_already:
        popf
        xor     eax, eax    ; already disabled
        ret

enable_irq: ;void (*)(int irq_no)
        mov     ecx, [esp + 4]      ; irq
        pushf
        cli
        mov     ah, ~1
        rol     ah, cl          ; ah = ~(1 << (irq % 8))
        cmp     cl, 8
        jae     enable_8        ; enable irq >= 8 at the slave 8259
    enable_0:
        in      al, INT_M_CTLMASK
        and     al, ah
        out     INT_M_CTLMASK, al       ; clear bit at master 8259
        popf
        ret
    enable_8:
        in      al, INT_S_CTLMASK
        and     al, ah
        out     INT_S_CTLMASK, al       ; clear bit at slave 8259
        popf
        ret
port_read: ; void (*)(u16 port, void* buf, int len)
    push ebp
    mov ebp, esp
    push edi
    mov edx, [ebp + 8]  ; port
    mov edi, [ebp + 12]  ; buf
    mov ecx, [ebp + 16] ; len
    shr ecx, 1
    cld
    rep insw
    pop edi
    leave
    ret

port_write: ; void (*)(u16 port, void* buf, int len);
	mov	edx, [esp + 4]		; port
	mov	esi, [esp + 4 + 4]	; buf
	mov	ecx, [esp + 4 + 4 + 4]	; len
	shr	ecx, 1
	cld
	rep	outsw
	ret
